package snmp

import (
	"fmt"
	"math"
	"pids-cloud-server/entity"
	"pids-cloud-server/logging"
)

// SnmpSwitchDataAcquisition /*交换机采集snmp实现*/
type SnmpSwitchDataAcquisition struct {
	SnmpDataAcquisition
}

// AcquireMemoryUsage /*采集内存使用情况*/
func (s *SnmpSwitchDataAcquisition) AcquireMemoryUsage(snmpOidMap map[string]entity.SnmpOid) (MemoryInfo, error) {
	g := s.Snmpclient
	var sum int
	var memSize int
	var memUsage float64
	if memList, err := g.BulkWalkAll(snmpOidMap[MEMORY_USAGE].OidValue); err == nil {
		for _, pdu := range memList {
			memusge := pdu.Value.(int)
			if memusge > 0 {
				sum += memusge
				memSize++
			}
		}
		memUsage = math.Round(float64(sum)*100/float64(memSize)) / 100
	}
	return MemoryInfo{MemoryUsage: memUsage}, nil
}

// AcquireCpu /*采集CPU信息*/
func (s *SnmpSwitchDataAcquisition) AcquireCpu(snmpOidMap map[string]entity.SnmpOid) (float64, error) {
	g := s.Snmpclient
	var sum int
	var cpuSize int
	var cpuUsage float64
	if cpuList, err := g.BulkWalkAll(snmpOidMap[CPU_USAGE].OidValue); err == nil {
		for _, pdu := range cpuList {
			cupusge := pdu.Value.(int)
			if cupusge > 0 {
				sum += cupusge
				cpuSize++
			}
		}
		if cpuSize >= 0 {
			cpuUsage = math.Round(float64(sum)*100/float64(cpuSize)) / 100
		}
	}
	return cpuUsage, nil
}

func (s *SnmpSwitchDataAcquisition) AcquirePortInfo(snmpOidMap map[string]entity.SnmpOid) ([]PortInfo, error) {
	var oidlist []string
	oidlist = append(oidlist, snmpOidMap[IF_DESCR].OidValue)
	oidlist = append(oidlist, snmpOidMap[IF_PHYS_ADDRESS].OidValue)
	oidlist = append(oidlist, snmpOidMap[IF_SPEED].OidValue)
	oidlist = append(oidlist, snmpOidMap[IF_OPER_STATUS].OidValue)
	g := s.Snmpclient
	descrList, err := g.BulkWalkAll(snmpOidMap[IF_DESCR].OidValue)
	if err != nil {
		return []PortInfo{}, fmt.Errorf("failed to perform BulkWalk for Port description: %v", err)
	}
	macList, err := g.BulkWalkAll(snmpOidMap[IF_PHYS_ADDRESS].OidValue)
	if err != nil {
		return []PortInfo{}, fmt.Errorf("failed to perform BulkWalk for IF_PHYS_ADDRESS:: %v", err)
	}
	speedList, err := g.BulkWalkAll((snmpOidMap[IF_SPEED].OidValue))
	if err != nil {
		return []PortInfo{}, fmt.Errorf("failed to perform BulkWalk for Port Speed:: %v", err)
	}
	statusList, err := g.BulkWalkAll((snmpOidMap[IF_OPER_STATUS].OidValue))
	if err != nil {
		return []PortInfo{}, fmt.Errorf("failed to perform BulkWalk for Port Status:: %v", err)
	}
	macMap := make(map[int]string)
	for i, pdu := range macList {
		mac := pdu.Value.([]byte)
		macMap[i] = fmt.Sprintf("%02x:%02x:%02x:%02x:%02x:%02x",
			mac[0], mac[1], mac[2], mac[3], mac[4], mac[5])
	}
	speedMap := make(map[int]uint)
	for i, pdu := range speedList {
		speedMap[i] = pdu.Value.(uint)
	}
	statusMap := make(map[int]int)
	for i, pdu := range statusList {
		statusMap[i] = pdu.Value.(int)
	}
	var portInfoList []PortInfo
	descMap := make(map[int]string)
	for i, pdu := range descrList {
		descMap[i] = string(pdu.Value.([]byte))
		portInfoList = append(portInfoList, PortInfo{
			PortName:   descMap[i],
			PortMac:    macMap[i],
			PortMaxBw:  int64(speedMap[i]),
			PortStatus: statusMap[i],
		})
	}
	return portInfoList, nil
}

func (s *SnmpSwitchDataAcquisition) AcquireTemperature(snmpOidMap map[string]entity.SnmpOid) (float64, error) {
	oidValue := snmpOidMap[TEMPERATURE].OidValue
	g := s.Snmpclient
	temperature, err := g.Get([]string{oidValue})
	if err != nil {
		logging.Error("SNMP get error:", err)
		return 0, fmt.Errorf("failed to get SNMP OIDs: %v", err)
	}
	return float64(temperature.Variables[0].Value.(int)), nil
}

func (s *SnmpSwitchDataAcquisition) AcquireSerialNumber(snmpOidMap map[string]entity.SnmpOid) (string, error) {
	oidValue := snmpOidMap[PHYSICALSERIALNUM].OidValue
	g := s.Snmpclient
	serialNumberPacket, err := g.Get([]string{oidValue})
	if err != nil {
		logging.Error("SNMP get error:", err)
		return "", fmt.Errorf("failed to get SNMP OIDs: %v", err)
	}
	serialNumber := string(serialNumberPacket.Variables[0].Value.([]byte))
	return serialNumber, nil
}
